import calc
import pygame
from typing import List
import draw
import time
import math

# 初始化 Pygame
pygame.init()

# 设置窗口大小
screen_width, screen_height = 800, 600
screen = pygame.display.set_mode((screen_width, screen_height))

# 设置窗口标题
pygame.display.set_caption("道路图绘制")

# 设置帧率的clock
clock = pygame.time.Clock()

# 设置颜色 (R, G, B)
black = (0, 0, 0)
white = (255, 255, 255)

fps = 30


def gameRun1(map: calc.Map, mov_pix: float, min_dis: float, mov_ang: float, min_ang: float):
    # 游戏主循环
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        # 填充背景色
        screen.fill(white)
        # 更新所有交通信号灯的状态
        map.updateAllTrafficLight()
        # 更新所有车辆的位置
        map.updateAllCarsPosition(mov_pix, min_dis, mov_ang, min_ang)
        # 生成新的车辆
        map.genNewCars(min_dis)
        # draw.drawline(screen, line, 3, black)
        draw.drawmap(screen, map, 3, black)

        # 更新屏幕
        pygame.display.flip()
        # 控制帧率
        clock.tick(fps)  # 设置帧率为30 FPS

if __name__ == '__main__':
    basev = 4
    # BSN BSS TBN TBS四个路口生成车辆的概率
    # TODO: 为什么这里概率大起来后，汽车生成的位置会变傻？
    genCarProbability = 0.1/fps
    # 四组路口的交通信号灯持续时间
    NS_last_time = {calc.STOP: 120, calc.GO: 20}
    WE_last_time = {calc.STOP: 20, calc.GO: 120}
    # 初始化时间
    start_time = time.time()
    # 初始化交通信号灯
    cr114 = calc.TrafficLight(start_time, 60, calc.GO, NS_last_time)
    cr123 = calc.TrafficLight(start_time, 60, calc.STOP, WE_last_time)
    cr258 = calc.TrafficLight(start_time, 0, calc.GO, NS_last_time)
    cr267 = calc.TrafficLight(start_time, 0, calc.STOP, WE_last_time)
    # 创建六个路口节点
    ehw = calc.Node(calc.NodeCoordinates(calc.Coordinates(0       ,0      ), calc.Rectangle(0    ,basev)), 3*genCarProbability, "ehw", None)
    cr1 = calc.Node(calc.NodeCoordinates(calc.Coordinates(3*basev ,0      ), calc.Rectangle(basev,basev)), 0*genCarProbability, "cr1", ehw )
    bsn = calc.Node(calc.NodeCoordinates(calc.Coordinates(0       ,-basev ), calc.Rectangle(basev,0    )), 1*genCarProbability, "bsn", cr1 )
    bss = calc.Node(calc.NodeCoordinates(calc.Coordinates(0       ,4*basev), calc.Rectangle(basev,0    )), 1*genCarProbability, "bss", cr1 )
    cr2 = calc.Node(calc.NodeCoordinates(calc.Coordinates(12*basev,0      ), calc.Rectangle(basev,basev)), 0*genCarProbability, "cr2", cr1 )
    tbn = calc.Node(calc.NodeCoordinates(calc.Coordinates(0       ,-basev ), calc.Rectangle(basev,0    )), 1*genCarProbability, "tbn", cr2 )
    tbs = calc.Node(calc.NodeCoordinates(calc.Coordinates(0       ,4*basev), calc.Rectangle(basev,0    )), 1*genCarProbability, "tbs", cr2 )
    ehe = calc.Node(calc.NodeCoordinates(calc.Coordinates(3*basev ,0      ), calc.Rectangle(0,basev    )), 3*genCarProbability, "ehe", cr2 )
    
    genCarNodes = {ehw, bsn, bss, tbn, tbs, ehe}
    trafficLightNodes = {cr1, cr2}
    roads: List[calc.Road] = []
    # 隔离带占路面宽度40%
    isolation_ratio = 0.4
    # List 创建道路列表
    roads.append(calc.Road([ehw, cr1], "[ehw, cr1]", isolation_ratio))
    roads.append(calc.Road([cr1, bsn], "[cr1, bsn]", 0.0))
    roads.append(calc.Road([cr1, bss], "[cr1, bss]", 0.0))
    roads.append(calc.Road([cr1, cr2], "[cr1, cr2]", isolation_ratio))
    roads.append(calc.Road([cr2, tbn], "[cr2, tbn]", 0.0))
    roads.append(calc.Road([cr2, tbs], "[cr2, tbs]", 0.0))
    roads.append(calc.Road([cr2, ehe], "[cr2, ehe]", isolation_ratio))
    # 构建地图 这里需要把道路列表、所有的生成汽车的路口节点以及所有的交通信号灯节点都传入地图中
    map = calc.Map(roads, genCarNodes, trafficLightNodes)
    times = map.getRealTimes(calc.Rectangle(screen_width, screen_height))
    # 在game不进行tas的情况下，汽车移动的速度(原始画布速度)
    width = basev*times
    originRspeed = width/5
    print("origin real speed = {:.8f}".format(originRspeed))
    print(times)
    print(map.getVirYOffset())
    map.updateNodeBias()
    map.updateNodeDraw()
    # 向两个路口加入四组交通信号灯
    cr1.add_trafficlight(cr114, calc.NSD)
    cr1.add_trafficlight(cr123, calc.WED)
    cr2.add_trafficlight(cr258, calc.NSD)
    cr2.add_trafficlight(cr267, calc.WED)
    # 地图生成路网的坐标
    map.genDrawLines()

    mov_pix = originRspeed*1.0/fps
    min_dis = originRspeed
    r = width/4
    mov_ang = math.asin((mov_pix/2)/r)*2
    min_ang = math.asin((min_dis/2)/r)*2

    gameRun1(map, mov_pix, min_dis, mov_ang, min_ang)
